package com.tangruojie.properties;

import jakarta.xml.bind.annotation.*;
import lombok.Data;

import java.util.List;

/**
 * JavaBean 类（带 JAXB 注解）
 * XML 本身并不能像 application.yaml 那样 直接由 Spring Boot 自动绑定到 JavaBean 中，因为 Spring Boot 的 @ConfigurationProperties 机制是专门为 .properties 和 .yml/.yaml 文件设计的，底层使用 Binder 去解析和绑定。
 * 但你可以通过 JAXB（Java Architecture for XML Binding） 实现类似功能：
 * 将 XML 配置文件中的结构映射为 JavaBean，并自动注入到 Spring 容器中使用。
 */

/**
 * 使用 JAXB 读取 XML 的时候，不支持直接绑定 Map<String, String>，因此需要使用 XmlMapEntry 包装键值对。
 * 日期字段需要用适配器处理。
 * 所有字段必须有 无参构造方法（@Data 已自动生成）。
 * 包名、类名要与你项目中一致。
 * JAXB 的版本在 Java 11+ 之后需要手动引入。
 */
@Data
@XmlRootElement(name = "myapp")
@XmlAccessorType(XmlAccessType.FIELD)
public class MyAppProperties {

    private String name;
    private String version;
    private int port;

    @XmlElement(name = "enable-logging")
    private boolean enableLogging;

    private String time;

    @XmlElementWrapper(name = "authors")
    @XmlElement(name = "author")
    private List<String> authors;

    private Metadata metadata;
    private Datasource datasource;
    private Limits limits;
    private User user;

    @XmlElementWrapper(name = "user-list")
    @XmlElement(name = "user")
    private List<User> userList;

    // 内部类
    @Data
    @XmlAccessorType(XmlAccessType.FIELD)
    public static class Metadata {
        private String env;
        private String region;
    }

    @Data
    @XmlAccessorType(XmlAccessType.FIELD)
    public static class Datasource {
        private String url;
        private String username;
        private String password;
    }

    @Data
    @XmlAccessorType(XmlAccessType.FIELD)
    public static class Limits {
        @XmlElement(name = "max-users")
        private int maxUsers;
        private Timeout timeout;

        @Data
        @XmlAccessorType(XmlAccessType.FIELD)
        public static class Timeout {
            private int connect;
            private int read;
        }
    }

    @Data
    @XmlAccessorType(XmlAccessType.FIELD)
    public static class User {
        private String name;
        private int age;
        private boolean male;
    }

}
